package zinx

import (
	"awesomeProject/zinx/utils"
	"awesomeProject/zinx/ziface"
	"errors"
	"fmt"
	"io"
	"net"
)

type Connection struct {
	Conn      *net.TCPConn
	ConnID    uint32
	IsClosed  bool
	ExitChan  chan bool
	MsgChan chan []byte
	MsgHandle ziface.IHandler
	TcpServer ziface.IServer
}

func NewConnection(server ziface.IServer,conn *net.TCPConn, connID uint32, mh ziface.IHandler) *Connection {
	c := &Connection{
		Conn:      conn,
		ConnID:    connID,
		IsClosed:  false,
		MsgHandle: mh,
		ExitChan:  make(chan bool, 1),
		MsgChan: make(chan []byte),
		TcpServer: server,
	}
	c.TcpServer.GetConnMgr().Add(c)
	return c
}

func (s *Server)GetConnMgr() ziface.IConnManager  {
	return s.ConnMr
}

func (c *Connection) startReader() {
	fmt.Println("Reader Coroutine is running ...")
	defer fmt.Println("connID=", c.ConnID, "Reader is exit,remote addr is", c.RemoteAddr().String())
	defer c.Stop()
	for {
		dp := NewDataPack()
		headData := make([]byte, dp.GetHeadLen())
		if _, err := io.ReadFull(c.GetTcpConnection(), headData); err != nil {
			fmt.Println("read msg head err", err)
			break
		}
		msg, err := dp.Unpack(headData)
		if err != nil {
			fmt.Println("unpack error", err)
			break
		}
		var data []byte
		if msg.GetMsgLen() > 0 {
			data = make([]byte, msg.GetMsgLen())
			if _, err := io.ReadFull(c.GetTcpConnection(), data); err != nil {
				fmt.Println("read data err", err)
				break
			}
		}
		msg.SetMsgData(data)
		fmt.Printf("recv client msg：%s \n", msg.GetMsgData())
		req := Request{
			conn: c,
			msg:  msg,
		}
		if utils.GlobalObject.WorkerPoolSize > 0 {
			c.MsgHandle.SendMsgToTaskQueue(&req)
		}else {
			go c.MsgHandle.DoMsgHandler(&req)
		}

	}
}

//写消息Goroutine,给客户端发消息
func (c *Connection) StartWriter()  {
	fmt.Println("writer goroutine running! ")
	defer fmt.Println(c.RemoteAddr().String(),"conn writer exit! ")
	//不断阻塞等等channel消息,进行写给客户端
	for {
		select {
		case data:= <- c.MsgChan:
			if _,err := c.Conn.Write(data);err != nil {
				fmt.Println("send data err",err)
				return
			}
		case <-c.ExitChan:
			return
		}
	}
}


func (c *Connection) Start() {
	fmt.Println("Conn Start()...ConnID=", c.ConnID)
	go c.startReader()
	go c.StartWriter()
}

func (c *Connection) Stop() {
	fmt.Println("Conn Stop()...ConnID=", c.ConnID)
	if c.IsClosed == true {
		return
	}
	c.IsClosed = true
	//关闭socket
	c.Conn.Close()

	c.ExitChan <- true
	//删除链接
	c.TcpServer.GetConnMgr().Remove(c)
	//回收资源
	close(c.ExitChan)
	close(c.MsgChan)
}

func (c *Connection) GetTcpConnection() *net.TCPConn {
	return c.Conn
}

func (c *Connection) GetConnId() uint32 {
	return c.ConnID
}

func (c *Connection) RemoteAddr() net.Addr {
	return c.Conn.RemoteAddr()
}

//数据先封包再发送给客户端
func (c *Connection) SendMsg(msgId uint32, data []byte) error {
	if c.IsClosed {
		return errors.New("Connection closed when send msg ")
	}
	//将data封包
	dp := NewDataPack()
	binaryMsg, err := dp.Pack(NewMsgPackage(msgId, data))
	if err != nil {
		fmt.Println("msg pack err", err)
		return errors.New("msg pack err")
	}
	//将数据发送给管道
	c.MsgChan <- binaryMsg
	return nil
}
